package yawning.mew.bear;

import yawning.mew.ProcEffect.Trigger;
import yawning.mew.character.CharacterModel.AttackResult;
import yawning.mew.sim.SimulationEvent;

public class MeleeEvent extends SimulationEvent {
	BearThreatSimulator mState;
	double mFurySwipesCooldownAt;

	public MeleeEvent(BearThreatSimulator state) {
		super(state.mSimEngine);

		mState = state;
	}

	@Override
	public void onTick() {
		AttackResult result = mState.mModel.getFrontalWhiteResult();

		if (result == AttackResult.MISS) {
			mNrWhiteMiss++;

			if (mState.mIsLogging) mState.mLog.log("White Swing: MISS\n");
		} else if (result == AttackResult.DODGE) {
			mNrWhiteDodge++;

			if (mState.mIsLogging) mState.mLog.log("White Swing: DODGE\n");
		} else if (result == AttackResult.PARRY) {
			mNrWhiteParry++;

			if (mState.mIsLogging) mState.mLog.log("White Swing: PARRY\n");
		} else {
			double damage = mState.mModel.getWeaponDamage();

			if (result == AttackResult.GLANCE) {
				mNrWhiteGlance++;
				damage *= 0.75;
			} else if (result == AttackResult.CRIT) {
				mNrWhiteCrit++;
				damage *= mState.mModel.multCrit;
			} else {
				mNrWhiteHit++;
			}

			damage *= mState.getDirectDamageMult();
			mWhiteDamage += Math.round(damage);

			if (mState.mIsLogging) mState.mLog.log("White Swing: %s Damage %d\n", result, Math.round(damage));

			if (result == AttackResult.CRIT) {
				mState.mSavageDefenseEv.onTrigger();
				mState.mLotPEv.onTrigger();
				mState.mSimEngine.triggerProc(mState.mActiveTarget, Trigger.WHITECRIT);
			} else {
				mState.mSimEngine.triggerProc(mState.mActiveTarget, Trigger.WHITE);
			}

			// As of Cataclysm, rage generation is normalized.
			int rage = (int) (6.5 * mState.mModel.getBaseWeaponSpeed());	// XXX: Is this correct for bears?
			mState.onRageGainThreat(rage);
			mRageGained += rage;

			if (result == AttackResult.CRIT) mState.onPrimalFuryTrigger();

			mState.mOoCEv.run();

			if (mFurySwipesCooldownAt <= mState.mSimEngine.getSimTime()) {
				if (mState.mSimEngine.getRandom().nextBoolean(mState.mModel.pFurySwipes)) {
					result = mState.mModel.getYellowResult();

					if (result == AttackResult.MISS) {
						mNrFurySwipesMiss++;

						if (mState.mIsLogging) mState.mLog.log("Fury Swipes: MISS\n");
					} else if (result == AttackResult.DODGE) {
						mNrFurySwipesDodge++;

						if (mState.mIsLogging) mState.mLog.log("Fury Swipes: DODGE\n");
					} else if (result == AttackResult.PARRY) {
						mNrFurySwipesParry++;

						if (mState.mIsLogging) mState.mLog.log("Fury Swipes: PARRY\n");
					} else {
						// BUG: Does not benefit from Bonus Weapon Damage (4.0.6 PTR)
						damage = mState.mModel.getWeaponDamage(true) * mState.mModel.multFurySwipes;

						if (result == AttackResult.CRIT) {
							mNrFurySwipesCrit++;
							damage *= mState.mModel.multCrit;
						} else {
							mNrFurySwipesHit++;
						}

						damage *= mState.getDirectDamageMult();
						mFurySwipesDamage += Math.round(damage);

						if (mState.mIsLogging) mState.mLog.log("Fury Swipes: %s Damage: %d\n",result, Math.round(damage));

						if (result == AttackResult.CRIT) {
							// This does NOT proc Savage Defense
							// XXX: Does this proc Primal Fury?
							mState.mLotPEv.onTrigger();
							mState.mSimEngine.triggerProc(mState.mActiveTarget, Trigger.WHITECRIT);
						} else {
							mState.mSimEngine.triggerProc(mState.mActiveTarget, Trigger.WHITE);
						}
					}

					mFurySwipesCooldownAt = mState.mSimEngine.getSimTime() + mState.mModel.furySwipesCDDuration;
				}
			}
		}
		setTickInterval(mState.mModel.getMeleeInterval());
	}

	public void start() {
		if (!isUp()) schedule(Double.MAX_VALUE, mState.mModel.getMeleeInterval());
	}

	public void stop() {
		cancel();
	}

	public void reset() {
		schedule(Double.MAX_VALUE, mState.mModel.getMeleeInterval());
	}

	long mWhiteDamage = 0;
	int mNrWhiteMiss = 0;
	int mNrWhiteDodge = 0;
	int mNrWhiteParry = 0;
	int mNrWhiteGlance = 0;
	int mNrWhiteCrit = 0;
	int mNrWhiteHit = 0;

	long mFurySwipesDamage = 0;
	int mNrFurySwipesMiss = 0;
	int mNrFurySwipesDodge = 0;
	int mNrFurySwipesParry = 0;
	int mNrFurySwipesCrit = 0;
	int mNrFurySwipesHit = 0;

	long mRageGained = 0;
}
